use config::Config;
use serde::Deserialize;
use std::sync::OnceLock;
use tklog::{debug, error, info};

#[derive(Debug, Clone, Deserialize)]
pub struct AppConfig {
    database: DatabaseSettings,
    server: ServerSettings,
    file_location: FileSettings,
    session: SessionSettings,
    admin: AdminSettings,
    certification: CertificationSettings,
}

#[derive(Debug, Clone, Deserialize)]
struct DatabaseSettings {
    host: String,
    port: u16,
    username: String,
    password: String,
    database: String,
}

#[derive(Debug, Clone, Deserialize)]
struct ServerSettings {
    host: String,
    port: u16,
}

#[derive(Debug, Clone, Deserialize)]
struct FileSettings {
    upload_location: String,
    archive_location: String,
    blog_home_dir: String,
}

#[derive(Debug, Clone, Deserialize)]
struct SessionSettings {
    timeout: u64,
}

#[derive(Debug, Clone, Deserialize)]
pub struct AdminSettings {
    pub username: String,
    pub password: String,
}

#[derive(Debug, Clone, Deserialize)]
pub struct CertificationSettings {
    public_key: String,
    private_key: String,
}

// 使用 OnceLock 实现配置的单例缓存
static CONFIG: OnceLock<AppConfig> = OnceLock::new();

impl AppConfig {
    /// 初始化配置，只应调用一次
    pub fn init() -> Result<(), Box<dyn std::error::Error>> {
        info!("Loading application configuration...");

        let configuration = Config::builder()
            .add_source(config::File::with_name("resource/application"))
            .build()
            .map_err(|e| {
                error!("Failed to load configuration: {}", e);
                e
            })?;

        let app_config: AppConfig = configuration.try_deserialize().map_err(|e| {
            error!("Failed to deserialize configuration: {}", e);
            e
        })?;

        CONFIG.set(app_config).map_err(|_| {
            let err_msg = "Configuration already initialized";
            error!("{}", err_msg);
            err_msg
        })?;

        debug!("Configuration loaded successfully");
        Ok(())
    }

    /// 获取配置实例
    pub fn get() -> &'static AppConfig {
        CONFIG.get().expect("Configuration not initialized")
    }

    /// 获取数据库连接URL
    pub fn get_database_connection_url(&self) -> String {
        format!(
            "mysql://{}:{}@{}:{}/{}",
            self.database.username,
            self.database.password,
            self.database.host,
            self.database.port,
            self.database.database
        )
    }

    pub fn get_server_host(&self) -> String {
        self.server.host.clone()
    }

    pub fn get_server_port(&self) -> u16 {
        self.server.port
    }

    pub fn get_certification(&self) -> (String, String) {
        (
            self.certification.public_key.clone(),
            self.certification.private_key.clone(),
        )
    }

    /// 获取服务器URL (优化性能，避免临时字符串分配)
    pub fn get_server_url(&self) -> String {
        let server = &self.server;
        format!("{}:{}", server.host, server.port)
    }

    pub fn get_file_upload_location(&self) -> String {
        self.file_location.blog_home_dir.clone()
            + self.file_location.upload_location.clone().as_str()
    }

    pub fn get_archive_location(&self) -> String {
        self.file_location.blog_home_dir.clone()
            + self.file_location.archive_location.clone().as_str()
    }

    pub fn get_session_timeout(&self) -> Option<u64> {
        Some(self.session.timeout)
    }

    pub fn get_admin_settings(&self) -> &AdminSettings {
        &self.admin
    }
}
